package com.module04.work.demo05;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/*使用基于 tcp 协议的编程模型实现多人同时在线聊天和传输文件，要求每个客户端将发
送的聊天内容和文件发送到服务器，服务器接收到后转发给当前所有在线的客户端。*/
//服务器
public class Server {
    //储存所有连接的客户端
    private final static ArrayList<ServerThread> clientList = new ArrayList<>();
    private final static String fileSrc = "/Users/wanggege/Desktop/ServerData/";

    public static void main(String[] args) {
        ServerSocket ss = null;
        Socket socket = null;
        try {
            //1.创建ServerScoket对象提供端口号
            ss = new ServerSocket(8888);
            //2.等待客户端连接请求调用accpet方法
            while (true) {
                System.out.println("等待客户端链接...");
                socket = ss.accept();
                ServerThread st = new ServerThread(socket);
                clientList.add(st);
                System.out.println("一个客户端连接成功！");
                // 每当有一个客户端连接成功，则需要启动一个新的线程为之服务
                st.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4.关闭Socket并释放有关的资源
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss != null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class ServerThread extends Thread {
        private Socket socket;
        private DataInputStream dis = null;
        private DataOutputStream dos = null;
        private String name;

        //构造方法并初始化
        public ServerThread(Socket socket) throws IOException {
            this.socket = socket;
            dis = new DataInputStream(socket.getInputStream());
            dos = new DataOutputStream(socket.getOutputStream());
            this.name = receiveMsg();
        }

        //接收客户端的消息
        public String receiveMsg() throws IOException {
            return dis.readUTF();
        }

        //转发客户端的消息
        public void sendMsg(String msg) throws IOException {
            dos.writeUTF(msg);
            dos.flush();
        }
        //发送文件
        public void sendFile() {
            try {
                dis = new DataInputStream(new FileInputStream(ReceiveFileThread.file));
                dos = new DataOutputStream(socket.getOutputStream());
                byte[] buff = new byte[1024];
                int res = 0;
                System.out.println(dis.read());
                while ((res = dis.read(buff)) != -1) {
                    dos.write(buff, 0, res);
                }
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        //向其他人发送消息
        public void sendOthers(String msg) throws IOException {
            for (ServerThread st : clientList) {
                if (st != this) {
                    if (msg.startsWith("sendFile:")) {
                        st.sendMsg("系统消息：接收" + this.name + "发来的文件成功！");
                    } else if (!msg.equals("")) {
                        st.sendMsg(this.name + "说: " + msg);
                    }
                }
            }
        }
        //向其他人发送文件
        public void sendOthersFile() throws IOException {
            for (ServerThread st : clientList) {
                if (st != this) {
                    st.sendFile();
                    }
                }
            }


        @Override
        public void run() {
            try {
                while (true) {
                    String msg = this.receiveMsg();
                    this.sendOthers(msg);
                    if (msg.startsWith("sendFile:")) {
                        new ReceiveFileThread(socket).start();
                    }
                    System.out.println(msg);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //接收客户端的文件到服务器的线程
    static class ReceiveFileThread extends Thread {
        private Socket socket;
        private DataInputStream dis = null;
        private DataOutputStream dos = null;
        private static long fileName = System.currentTimeMillis();
        private static File file = null;


        //构造方法并初始化
        public ReceiveFileThread(Socket socket) throws IOException {
            this.socket = socket;
            this.file = new File(fileSrc + fileName + ".txt");
            dis = new DataInputStream(socket.getInputStream());
            dos = new DataOutputStream(new FileOutputStream(file));

        }

        //接收客户端的文件并转发
        public boolean receiveFile() {
            try {
                byte[] buff = new byte[1024];
                int res = 0;
                while ((res = dis.read(buff)) != -1) {
                    dos.write(buff, 0, res);
                    System.out.println(res);
                }
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return true;
        }


        @Override
        public void run() {
            receiveFile();
        }
    }

}
